#pragma once
#include <iostream>
#include <sys/select.h>
#include "Common.hpp"
#include "Socket.hpp"
#include <vector>
using namespace std;
using namespace SocketMoudle;
class selectServer
{
private:
    unique_ptr<Socket> _listenSocket;
    bool _running = true;
    const static int size = sizeof(fd_set) * 8;
    int defaulted = -1;
    vector<int> fd_array;
    ;

public:
    selectServer(int port) : _listenSocket(make_unique<TcpSocket>(port))
    {
        _listenSocket->BuildListenSocket(port);
        fd_array.resize(size, defaulted);
    }
    ~selectServer() {}
    void start()
    {
        while (_running)
        {
            // 将listenSocket加入到select中,让select关心listenSocket的读事件
            fd_set readfds;    // 读文件描述符集
            FD_ZERO(&readfds); // 清空文件描述符集
            // FD_SET(_listenSocket->GetSockFd(),&readfds);//将listenSocket加入到文件描述符集中
            // 借助辅助数组保存服务器历史获取过的所有fd
            // struct timeval timeout={2,0};//设置超时时间为2秒
            // 最大的fd一定是变化的，每一次都要重置
            fd_array[0] = _listenSocket->GetSockFd();
            int maxfd = -1;
            for (int fd : fd_array)
            {
                if (fd != defaulted)
                {
                    FD_SET(fd, &readfds);
                    maxfd = max(maxfd, fd);
                }
            }
            int n = select(maxfd + 1, &readfds, nullptr, nullptr, nullptr);
            switch (n)
            {
            case -1:
                LOG(LogLevel::ERROR) << "select error";
                break;
            case 0:
                LOG(LogLevel::INFO) << "select timeout";
                break;
            default:
                LOG(LogLevel::INFO) << "select has event";
                Dispatcher(readfds);
                break;
            }
        }
        _running = false;
    }
    void PrintFd()
    {
        for (int fd : fd_array)
        {
            if (fd != defaulted)
            {
                cout << fd << endl;
            }
        }
    }
    void Dispatcher(fd_set &readfds)
    {
        // 处理listenSocket的读事件
        for (int i = 0; i < fd_array.size(); i++)
        {
            if (FD_ISSET(fd_array[i], &readfds))
            {
                if (fd_array[i] == _listenSocket->GetSockFd())
                {
                    // 处理listenSocket的读事件
                    AcceptNewClient();
                }
                else
                {
                    // 处理其他客户端
                    Recever(fd_array[i], i);
                }
            }
        }
    }
    void AcceptNewClient()
    {

        NetAddr client;
        int fd = _listenSocket->Accept(&client); // 不会阻塞，套接字已就绪
        if (fd >= 0)
        {
            LOG(LogLevel::INFO) << "accept a new client:" + client.stringaddr();
            // 将新的客户端加入到辅助数组中
            int i = 0;
            for (; i < fd_array.size(); i++)
            {
                if (fd_array[i] == defaulted)
                {
                    break;
                }
            }
            if (i == fd_array.size())
            {
                LOG(LogLevel::WARNING) << "达到最大连接数，无法接收新连接";
                close(fd);
            }
            else
            {
                fd_array[i] = fd;
            }
        }
    }
    void Recever(int fd, int i)
    {
        char buffer[1024];
        ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            LOG(LogLevel::INFO) << "收到客户端数据:" << buffer;
        }
        else if (n == 0)
        {
            LOG(LogLevel::INFO) << "客户端断开连接";
            close(fd);
            // 将客户端fd从辅助数组中移除
            fd_array[i] = defaulted;
        }
        else
        {
            LOG(LogLevel::ERROR) << "接收数据失败";
        }
    }
    void stop()
    {
        _running = false;
    }
};